﻿using CalculatorOperationAPI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting;
using System.Text;

namespace Calculator
{
    class Program
    {
        static List<ServiceDetails> registeredOperations = new List<ServiceDetails>();

        static void Main(string[] args)
        {
            Console.Title = "Calculator";

            //1- Register operations to the used by the application
            registeredOperations.Add(new ServiceDetails() {DisplayName = "Add", Namespace = "Operations", TypeName = "Operations.Add" });
            registeredOperations.Add(new ServiceDetails() { DisplayName = "Subtract", Namespace = "Operations", TypeName = "Operations.Subtract" });


            //2- Display all the registerd operation to the user to select the required operation 
            for(int i = 0; i < registeredOperations.Count(); i ++)
            {
                ServiceDetails service = registeredOperations[i];
                Console.WriteLine(string.Format("{0} : {1}",i,service.DisplayName));
            }

            //3- User must select the operation to number to be used
            Console.WriteLine("");
            Console.Write("Select Operation Number : ");
            int OperationNumber;
            string operation = Console.ReadLine();
            Console.WriteLine("");

            //4- Get the details of the selected operation from the registed services list
            ServiceDetails operationDetails = null;
            if (int.TryParse(operation, out OperationNumber) && OperationNumber <= registeredOperations.Count())
                operationDetails = registeredOperations[OperationNumber];

            if (operationDetails == null)
            {
                //if the user enter a wrong operation number (Not listed operation)
                Console.WriteLine("Operation Not Found");
            }
            else
            {
                //5- Use the Registed operation to calculate the value by intiate a new object on the runtime
                ObjectHandle obj = Activator.CreateInstance(operationDetails.Namespace, operationDetails.TypeName);

                //6- Cast this object to the IOperation interface
                IOperation operationImplementation = (obj.Unwrap()) as IOperation;

                //7- Use the interface to get list of required paramters for this application
                Dictionary<string, string> parameters = new Dictionary<string, string>();
                
                //8- Ask the user to enter the paramters value
                List<string> listOfParamters = operationImplementation.GetOperaionParameters();
                foreach (var paramName in listOfParamters)
                {
                    Console.Write(string.Format("{0} : ",paramName));
                    parameters.Add(paramName, Console.ReadLine());
                }

                //9- Use the interface to calculate the result and display it to the user
                Console.WriteLine("");
                Console.WriteLine(string.Format("The result is : {0}",operationImplementation.Calculate(parameters)));
            }

            Console.WriteLine("Press any key to exit....");
            Console.ReadKey();
        }
    }

    class ServiceDetails
    {
        public string DisplayName { get; set; }
        public string Namespace { get; set; }
        public string TypeName { get; set; }
    }
}
